﻿#define _CRT_SECURE_NO_WARNINGS	

#include<stdio.h>

//判断大小端存储
//方法一：
//int main()
//{
//	//我们假定一个数
//	int num = 1; //其在内存中存储（16禁止表示）：00 00 00 01
//
//	//如果它为小端存储，那么其第一个字节的内容一定是01
//	//如果它为大端存储，那么其第一个字节的内容一定是00
//
//	char* p = (char*) &num;
//
//	if (*p == 1)
//	{
//		printf("小端存储\n");
//	}
//	else
//	{
//		printf("大端存储\n");
//	}
//
//
//	return 0;
//}

//方法二：
//int main()
//{
//	typedef union Un
//	{
//		char ch;
//		int i;
//	}Un;
//
//	Un un;
//	un.i = 1;
//
//	if (un.ch == 1)
//	{
//		printf("小端存储\n");
//	}
//	else
//	{
//		printf("大端存储\n");
//	}
//
//	return 0;
//}
//
//#include <stdio.h>
//int main()
//{
//	int n = 9;
//	float* pFloat = (float*)&n;
//	printf("n的值为：%d\n", n);
//	printf("*pFloat的值为：%f\n", *pFloat);
//
//	*pFloat = 9.0;
//	printf("num的值为：%d\n", n);
//	printf("*pFloat的值为：%f\n", *pFloat);
//	return 0;
//}


//数据在内存中存储的相关知识点题目
//请说出下面分别打印的值：

//题目1：
//#include <stdio.h>
//int main()
//{
//	char a = -1;
//	signed char b = -1;
//	unsigned char c = -1;
//	printf("a=%d,b=%d,c=%d", a, b, c);    
//	printf("\n");
//	return 0;
//}

//题目2(值得反复琢磨)：
//#include <stdio.h>
//int main()
//{
//	char a = -128; //-128的原码：1000 0000 ，反码：0111 1111 .补码：1000 0000
//	//这里我要特别说明一句：但符号位起到了不仅仅是符号的作用，它还起到了数值位的效果
//	//此时，就要按照数值位的规则了，该取反的地方就取反。
//	printf("%ud\n", a);
//	//%ud是以无符号整数的形式读取a的数值，但是一个整数个占4个字节，而字符只占1个字节
//	// 那为什么可以这样操作呢？
//	// 数字在内存中是以二进制存储的，而变量名只是该地址的一个抽象化表示，我们不能被变量名所迷惑，
//	// 我们存储的数据如何被读取和存储的，主要是依靠数据类型的视角来看待问题。
//	// 这里你会发现是一个整型的值赋值给了一个字符类型的变量，编译器允许这种操作。
//	// 而在ASCI C中被称为：截断现象
//	//-128在32位的平台下：
//	//10000000 00000000 00000000 10000000(原码)
//	//11111111 11111111 11111111 01111111(反码)
//	//11111111 11111111 11111111 10000000(补码)->这个才是最后打印出来的值
//	return 0;
//}

//题目3：
//#include <stdio.h>
//int main()
//{
//	char a = 128;//（截断）
//	//128的原码：00000000 00000000 00000000 10000000
//	//128的反码：00000000 00000000 00000000 10000000
//	//128的补码：00000000 00000000 00000000 10000000
//	printf("%u\n", a);//11111111 11111111 11111111 10000000（整型提升）
//	return 0;
//}



//题目4：
//#include<stdio.h>
//#include<string.h>
//int main()
//{
//	char a[1000]; //char类型的所能表示的数据范围是-128~127
//	int i = 0;
//
//	for (i = 0; i < 1000; i++)
//	{
//		a[i] = -1 - i; //-1...-128
//	}
//	//-128的补码：10000000 00000000 00000000 10000000
//	//-1的补码：  11111111 11111111 11111111 11111111
//	//所以-1-128 = 10000000 00000000 00000000 01111111
//	//发生截断之后：01111111，为此，a[128]的值就有变为了127
//	//-1...-128 127 ...0
//	//128+127 = 255
//
//	printf("%zd\n",strlen(a));
//	return 0;
//}

//题目5：
//#include <stdio.h>
//unsigned char i = 0;
//int main()
//{
//	for (i = 0; i <= 255; i++)
//	{
//		printf("hello world\n");
//	}
//	return 0;
//}

//题目6：
//#include <stdio.h>
//#include<windows.h>
//int main()
//{
//	unsigned int i;
//	for (i = 9; i >= 0; i--)
//	{
//		printf("%u\n", i);
//		Sleep(1000);
//	}
//	return 0;
//}

//题目7(有问题)：
#include <stdio.h>
////X86环境 ⼩端字节序
int main()
{
	int a[4] = { 1, 2, 3, 4 };
	int* ptr1 = (int*)(&a + 1); //&a:整个数组的地址，&a+1相当于跳过了数组a
	int* ptr2 = (int*)((int)a + 1);//数组名相当于首元素的地址
	printf("%x,%x", ptr1[-1], *ptr2);
	//ptr[-1]:0x00000004 -> 04 00 00 00
	//*ptr2:
	return 0;
}


//#include<stdio.h>
//int main()
//{
//	int a = 100;
//	float f = 100.0f;
//
//	float tmp = a + f;
//
//	printf("%.2f",tmp);
//
//	return 0;
//}

//整型提升（仅限于整型家族）
//验证的代码
//#include<stdio.h>
//int main()
//{
//	char a = 0x86; //1000 0110(十六进制对应的二进制)
//	short b = 0x8600; //1000 0110 0000 0000(十六进制对应的二进制)
//	int c = 0x86000000; //10000110 00000000 00000000 00000000(十六进制对应的二进制)
//
//	if (0x86 == a)
//		printf("%c\n",'a');
//
//	if (0x8600 == b)
//		printf("%c\n", 'b');
//
//	if (0x86000000 == c)
//		printf("%c\n", 'c');
//
//	return 0;
//}



//#include<stdio.h>

//int main()
//{
//	char a = 128;
//	printf("%x\n",a);
//
//	char b = -128;
//	printf("%x\n", b);
//
//}


//int main()
//{
//	float f = 10.5f;
//	int a = f;
//
//	printf("a = %d\n",a);
//
//	return 0;
//}
